import re
from rest_framework import serializers
from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler
from . import models
from django.core.cache import cache
from django.conf import settings

"""
@author RansySun
@create 2019-12-02-19:04
"""


class LoginModelsSerializer(serializers.ModelSerializer):
    """
    多种登录方式
    """
    username = serializers.CharField(min_length=3, max_length=20, write_only=True)
    password = serializers.CharField(min_length=6, max_length=12, write_only=True)

    class Meta:
        model = models.User
        fields = ("username", "password")

    # 校验user,签发token,保存至serializer
    def validate(self, attrs):
        # 账号密码登录（多方式登录）
        user_obj = self._many_method_login(**attrs)

        # 签发token, 并将user_obj,和token存放在序列化对象中
        payload = jwt_payload_handler(user_obj)
        token = jwt_encode_handler(payload)

        self.user = user_obj
        self.token = token

        return attrs

    def _many_method_login(self, **attrs):
        """
        多种登录方式实现
        :param attrs: 验证的数据
        :return: 返回当前登录对象
        """
        print(attrs)

        username = attrs.get("username")
        password = attrs.get("password")

        # 判断登录方式
        if re.match(r".*@.*", username):
            user_obj = models.User.objects.filter(email=username).first()  # type: models.User
        elif re.match(r"^1[3-9][0-9]{9}$", username):
            user_obj = models.User.objects.filter(mobile=username).first()
        else:
            user_obj = models.User.objects.filter(username=username).first()

        if not user_obj:
            raise serializers.ValidationError({"username": "账号有误"})

        if not user_obj.check_password(password):
            raise serializers.ValidationError({"password": "密码有误"})

        return user_obj


class LoginMobileSerializer(serializers.ModelSerializer):
    """手机验证码登录"""
    mobile = serializers.CharField(write_only=True, min_length=11, max_length=11)
    code = serializers.CharField(write_only=True, min_length=4, max_length=4)

    class Meta:
        model = models.User
        fields = ("mobile", "code")

    def validate_mobile(self, value):
        if re.match(r"^1[3-9][0-9]{9}$", value):
            return value
        raise serializers.ValidationError({"mobile": "手机号错误！"})

    def validate_code(self, value):

        try:
            int(value)
            return value
        except:
            raise serializers.ValidationError({"code": "验证码格式错误！"})

    # 校验user, 签发token,保存到serializer
    def validate(self, attrs):
        user_obj = self._get_user(**attrs)

        # 签发token，并将user和token存放到序列化对象中
        payload = jwt_payload_handler(user_obj)
        token = jwt_encode_handler(payload)

        self.user = user_obj
        self.token = token
        return attrs

    def _get_user(self, **attrs):
        mobile = attrs.get("mobile")
        code = attrs.get("code")

        user_obj = models.User.objects.filter(mobile=mobile).first()
        if not user_obj:
            raise serializers.ValidationError({"mobile": "该手机号未被注册！"})

        # 拿到之前缓存的验证码对比
        old_code = cache.get(f"{settings.SMS_CACHE_KEY}{mobile}")
        # print(old_code, code)
        if code != old_code:
            raise serializers.ValidationError({"code": "验证码有误！"})

        # 为了保证验证码的安全，验证码验证成功之后，失效
        # cache.set(f"{settings.SMS_CACHE_KEY}{mobile}", "0000", 0)

        return user_obj


class RegisterModelSerializer(serializers.ModelSerializer):
    code = serializers.CharField(write_only=True, min_length=4, max_length=4)

    class Meta:
        model = models.User
        fields = ("mobile", "password", "code")

    def validate_mobile(self, value):
        if re.match(r"^1[3-9][0-9]{9}$", value):
            return value
        raise serializers.ValidationError({"mobile": "手机号错误！"})

    def validate_code(self, value):

        try:
            int(value)
            return value
        except:
            raise serializers.ValidationError({"code": "验证码格式错误！"})

    def validate_password(self, value):
        # 密码不能包含特殊字符
        # value_str = []
        # for i in range(len(value)):
        #     value_str.append(value[0])

        # if "*" in value:
        #     raise serializers.ValidationError({"password": "不能包含特殊字符！"})
        if "*" in value:
            raise serializers.ValidationError({"password": "不能包含特殊字符！"})
        return value

    def validate(self, attrs):
        mobile = attrs.get("mobile")
        code = attrs.pop("code")
        old_code = cache.get(f"{settings.SMS_CACHE_KEY}{mobile}")

        # 判断手机号是否被注册
        user_obj = models.User.objects.filter(mobile=mobile).first()
        if user_obj:
            raise serializers.ValidationError({"mobile": "该手机号已被注册！"})

        # 判断两次密码是否一样
        if code != old_code:
            raise serializers.ValidationError({"code": "验证码有误"})

        # 清除一次性验证码，使用过一次就不可以使用
        cache.set(f"{settings.SMS_CACHE_KEY}{mobile}", "0000", 0)

        # 设置默认的用户名和邮箱
        attrs["username"] = mobile
        attrs['email'] = f"{mobile}@randy.com"

        return attrs

    # User表必须重写create方法，才能操作密文密码
    def create(self, validated_data):

        return models.User.objects.create_user(**validated_data)
